package com.soccerlover9527.jadis.datasturct.impl;

import com.soccerlover9527.jadis.datasturct.AbstractJadisObject;
import com.soccerlover9527.jadis.datasturct.JHash;
import com.soccerlover9527.jadis.enums.DataType;
import com.soccerlover9527.jadis.exception.OperationNotSupportException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p></p>
 *
 * @author soccerlover9527@gmail.com
 * @since 2023-08-07
 */
public class JadisHash<K, V> extends AbstractJadisObject implements JHash<K, V> {
    private final Map<K, V> map;

    public JadisHash() {
        super(DataType.HASH);
        map = new HashMap<>();
    }

    public JadisHash(Map<K, V> map) {
        super(DataType.HASH);
        this.map = map;
    }

    @Override
    public int put(K key, V value) {
        V previous = map.put(key, value);
        return previous == null ? 1 : 0;
    }

    @Override
    public int delete(K key) {
        V remove = map.remove(key);
        return remove == null ? 0 : 1;
    }

    @Override
    public V get(K key) {
        return map.get(key);
    }

    @Override
    public boolean exist(K key) {
        return map.containsKey(key);
    }

    @Override
    public List<?> getAll() {
        return map.entrySet().stream()
                .flatMap(entry -> Stream.of(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    @SuppressWarnings("unchecked")
    public long increment(K key, long addend) {
        var v = map.get(key);
        if (v == null) {
            try {
                v = (V) new JadisString("0");
                map.put(key, v);
            } catch (ClassCastException cce) {
                throw new OperationNotSupportException("This hash table not support increment operation.");
            }
        }
        if (!(v instanceof JadisString)) {
            throw new OperationNotSupportException("Can't increase value, because unsupported type:" + v.getClass());
        }
        return ((JadisString) v).increment();
    }

    @Override
    public List<K> keys() {
        return map.keySet().stream().toList();
    }

    @Override
    public List<V> values() {
        return map.values().stream().toList();
    }

    @Override
    public int length() {
        return map.size();
    }
}
